home *** CD-ROM | disk | FTP | other *** search
/ Hot Super Models / Hot Super Models.iso / unix / x11 / xv200.tar / xv-2.00 / xvps.c < prev    next >
C/C++ Source or Header  |  1992-01-02  |  29KB  |  1,077 lines

  1. /* 
  2.  * xvps.c - Postscript dialog box, file output functions
  3.  *
  4.  * callable functions:
  5.  *
  6.  *   CreatePSD(geom)           -  creates the psW window.  Doesn't map it.
  7.  *   PSDialog()                -  maps psW
  8.  *   PSCheckEvent(event)       -  called by event handler
  9.  *   PSSaveParams(str,int)     -  tells PSDialog what to do when 'Ok' clicked
  10.  *   PSResize()                -  called whenever ePic changes size
  11.  */
  12.  
  13. /*
  14.  * Copyright 1989, 1990, 1991, 1992 by John Bradley and
  15.  *                       The University of Pennsylvania
  16.  *
  17.  * Permission to use, copy, and distribute for non-commercial purposes,
  18.  * is hereby granted without fee, providing that the above copyright
  19.  * notice appear in all copies and that both the copyright notice and this
  20.  * permission notice appear in supporting documentation.
  21.  *
  22.  * The software may be modified for your own purposes, but modified versions
  23.  * may not be distributed.
  24.  *
  25.  * This software is provided "as is" without any expressed or implied warranty.
  26.  *
  27.  * The author may be contacted via:
  28.  *    US Mail:   John Bradley
  29.  *               GRASP Lab, Room 301C
  30.  *               3401 Walnut St.
  31.  *               Philadelphia, PA  19104
  32.  *
  33.  *    Phone:     (215) 898-8813
  34.  *    EMail:     bradley@cis.upenn.edu
  35.  */
  36.  
  37.  
  38. #include "xv.h"
  39.  
  40. #define PSWIDE 431
  41. #define PSHIGH 340
  42. #define PMAX   200    /* size of square that a 'page' has to fit into */
  43.  
  44. #define PS_NBUTTS 6
  45. #define PS_BOK    0
  46. #define PS_BCANC  1
  47. #define PS_BCENT  2
  48. #define PS_BMAX   3
  49. #define PS_BPOSX  4
  50. #define PS_BPOSY  5
  51.  
  52. /* paperRB indicies */
  53. #define PSZ_NORM  0
  54. #define PSZ_A4    1
  55. #define PSZ_B5    2
  56. #define PSZ_LEGAL 3
  57. #define PSZ_BSIZE 4
  58.  
  59. /* orientRB indicies */
  60. #define ORNT_PORT 0
  61. #define ORNT_LAND 1
  62.  
  63. #define BUTTH 24
  64.  
  65. #define IN2CM 2.54
  66.  
  67. #define PIX2INCH 72.0   /* # of pixels per inch, at 100% scaling */
  68.  
  69. #ifdef __STDC__
  70. static void drawPSD(int, int, int, int);
  71. static void drawPosStr();
  72. static void drawSizeStr();
  73. static void drawResStr();
  74. static void drawPage();
  75. static void clickPSD(int, int);
  76. static void clickPage(int, int);
  77. static void doCmd(int);
  78. static void changedScale(void);
  79. static void setScale(void);
  80. static void changedPaper(void);
  81. static void setPaper(void);
  82. static void drawIRect(int);
  83. static void centerImage(void);
  84. static void maxImage(void);
  85. static void moveImage(double, double);
  86. static void writePS(void);
  87. static void psColorImage();
  88. static void epsPreview();
  89. static int  writeBWStip(FILE *, byte *, char *);
  90. #else
  91. static void drawPSD(), drawPosStr(), drawSizeStr(), drawResStr();
  92. static void drawPage(), clickPSD(), clickPage(), doCmd(), changedScale();
  93. static void setScale(), changedPaper(), setPaper(), drawIRect();
  94. static void centerImage(), maxImage(), moveImage(), writePS(), psColorImage();
  95. static void epsPreview();
  96. static int  writeBWStip();
  97. #endif
  98.  
  99.  
  100. /* local variables */
  101. static Window pageF;
  102. static DIAL   xsDial, ysDial;
  103. static RBUTT *orientRB, *paperRB;
  104. static CBUTT  lockCB;
  105. static BUTT   psbut[PS_NBUTTS];
  106. static double sz_inx, sz_iny;     /* image size, in inches */
  107. static double pos_inx, pos_iny;   /* top-left offset of image, in inches */
  108. static int    dpix, dpiy;         /* # of image pixels per inch */
  109. static int    tracking=0;         /* used in changedScale */
  110. static int    posxType, posyType;
  111.  
  112. /* sizes of pages in inches */
  113. static double paperSize[5][2] = { { 8.500, 11.000},   /* US NORMAL */
  114.                   { 8.267, 11.811},   /* A4 */
  115.                   { 7.283, 10.630},   /* B5 */
  116.                   { 8.500, 14.000},   /* US LEGAL */
  117.                   {11.000, 17.000}};  /* B-size */
  118.  
  119. static double psizex, psizey;   /* current paper size, in inches */
  120. static double in2pix;           /* inch to pixels in 'pageF' */
  121. static XRectangle pageRect;     /* bounding rect of page, in screen coords */
  122.  
  123. static char *filename;          /* filename to save to */
  124. static int   colorType;         /* value of 'Colors' rbutt in dir box */
  125. static int   firsttime=1;       /* first time PSDialog being opened ? */
  126.  
  127.  
  128. /***************************************************/
  129. void CreatePSD(geom)
  130. char *geom;
  131. {
  132.   CARD32     data[2];
  133.   Atom       prop;
  134.  
  135.   psW = CreateWindow("xv postscript", geom, PSWIDE, PSHIGH, infofg, infobg);
  136.   if (!psW) FatalError("can't create postscript window!");
  137.  
  138.   data[0] = (CARD32) XInternAtom(theDisp, "WM_DELETE_WINDOW", FALSE);
  139.   data[1] = (CARD32) time((long *)0);
  140.   prop = XInternAtom(theDisp, "WM_PROTOCOLS", FALSE),
  141.   XChangeProperty(theDisp, psW, prop, prop,
  142.           32, PropModeReplace, (unsigned char *) data, 2);
  143.  
  144.   pageF = XCreateSimpleWindow(theDisp, psW, 20,30, PMAX+1,PMAX+1,
  145.                   1,infofg,infobg);
  146.   if (!pageF) FatalError("couldn't create frame windows");
  147.  
  148.   XSetWindowBackgroundPixmap(theDisp, pageF, grayTile);
  149.  
  150.   XSelectInput(theDisp, pageF, ExposureMask | ButtonPressMask);
  151.   XSelectInput(theDisp, psW,   ExposureMask | ButtonPressMask | KeyPressMask);
  152.  
  153.  
  154.   DCreate(&xsDial, psW, 240, 30, 80, 100, 10, 800, 100, 5, 
  155.       infofg, infobg, "Width", "%");
  156.   DCreate(&ysDial, psW, 331, 30, 80, 100, 10, 800, 100, 5, 
  157.       infofg, infobg, "Height", "%");
  158.   xsDial.drawobj = changedScale;
  159.   ysDial.drawobj = changedScale;
  160.  
  161.   CBCreate(&lockCB, psW, 319, 136, "", infofg, infobg);
  162.   lockCB.val = 1;
  163.  
  164.   orientRB = RBCreate(NULL, psW, 36, 240+18, "Portrait", infofg, infobg);
  165.   RBCreate(orientRB, psW, 36+80, 240+18, "Landscape", infofg, infobg);
  166.  
  167.   paperRB = RBCreate(NULL, psW, 36, 240+18+36, "8.5\"x11\"", infofg, infobg);
  168.   RBCreate(paperRB, psW, 36+80,    240+18+36, "A4",         infofg, infobg);
  169.   RBCreate(paperRB, psW, 36+154,   240+18+36, "B5",         infofg, infobg);
  170.   RBCreate(paperRB, psW, 36,       240+36+36, "8.5\"x14\"", infofg, infobg);
  171.   RBCreate(paperRB, psW, 36+80,    240+36+36, "11\"x17\"",  infofg, infobg);
  172.  
  173.   BTCreate(&psbut[PS_BOK], psW, PSWIDE-160, PSHIGH-10-BUTTH, 60, BUTTH, 
  174.        "Ok", infofg, infobg);
  175.  
  176.   BTCreate(&psbut[PS_BCANC], psW, PSWIDE-80, PSHIGH-10-BUTTH, 60, BUTTH, 
  177.        "Cancel", infofg, infobg);
  178.  
  179.   BTCreate(&psbut[PS_BCENT], psW, 240, 153, 88, BUTTH, 
  180.        "Center", infofg, infobg);
  181.  
  182.   BTCreate(&psbut[PS_BMAX], psW, 240+88+5, 153, 87, BUTTH, 
  183.        "Maxpect", infofg, infobg);
  184.  
  185.   BTCreate(&psbut[PS_BPOSX], psW, 256-14, 190+13-8, 8,8, "", infofg, infobg);
  186.   BTCreate(&psbut[PS_BPOSY], psW, 256-14, 190+26-8, 8,8, "", infofg, infobg);
  187.  
  188.   posxType = posyType = 0;
  189.   pos_inx = 1.0;  pos_iny = 1.0;   /* temporary bootstrapping... */
  190.   setPaper();
  191.   setScale();
  192.  
  193.   XMapSubwindows(theDisp, psW);
  194. }
  195.   
  196.  
  197. /***************************************************/
  198. void PSDialog(vis)
  199. int vis;
  200. {
  201.   if (vis) {
  202.     setScale();
  203.     if (firsttime) centerImage();
  204.     firsttime = 0;
  205.     CenterMapWindow(psW, psbut[PS_BOK].x + psbut[PS_BOK].w/2,
  206.             psbut[PS_BOK].y + psbut[PS_BOK].h/2, PSWIDE, PSHIGH);
  207.   }
  208.   else     XUnmapWindow(theDisp, psW);
  209.   psUp = vis;
  210. }
  211.  
  212.  
  213. /***************************************************/
  214. int PSCheckEvent(xev)
  215. XEvent *xev;
  216. {
  217.   /* check event to see if it's for one of our subwindows.  If it is,
  218.      deal accordingly, and return '1'.  Otherwise, return '0' */
  219.  
  220.   int rv;
  221.   rv = 1;
  222.  
  223.   if (!psUp) return 0;
  224.  
  225.   if (xev->type == Expose) {
  226.     int x,y,w,h;
  227.     XExposeEvent *e = (XExposeEvent *) xev;
  228.     x = e->x;  y = e->y;  w = e->width;  h = e->height;
  229.  
  230.     /* throw away excess expose events for 'dumb' windows */
  231.     if (e->count > 0 && 
  232.     (e->window == xsDial.win || e->window == ysDial.win ||
  233.      e->window == pageF)) {}
  234.  
  235.     else if (e->window == psW)         drawPSD(x, y, w, h);
  236.     else if (e->window == xsDial.win)  DRedraw(&xsDial);
  237.     else if (e->window == ysDial.win)  DRedraw(&ysDial);
  238.     else if (e->window == pageF)       drawPage();
  239.     else rv = 0;
  240.   }
  241.  
  242.   else if (xev->type == ButtonPress) {
  243.     XButtonEvent *e = (XButtonEvent *) xev;
  244.     int i,old,x,y;
  245.     x = e->x;  y = e->y;
  246.  
  247.     if (e->button == Button1) {
  248.       if      (e->window == psW)   clickPSD(x,y);
  249.       else if (e->window == pageF) clickPage(x,y);
  250.  
  251.       else if (e->window == xsDial.win || e->window == ysDial.win) {
  252.     if (e->window == xsDial.win) {
  253.       tracking = 1;
  254.       DTrack(&xsDial, x,y);
  255.       tracking = 0;
  256.     }
  257.  
  258.     else if (e->window == ysDial.win) {
  259.       tracking = 2;
  260.       DTrack(&ysDial, x,y);
  261.       tracking = 0;
  262.     }
  263.       }
  264.       else rv = 0;
  265.     }  /* button1 */
  266.     else rv = 0;
  267.   }  /* button press */
  268.  
  269.  
  270.   else if (xev->type == KeyPress) {
  271.     XKeyEvent *e = (XKeyEvent *) xev;
  272.     char buf[128];  KeySym ks;  XComposeStatus status;  
  273.     int stlen;
  274.     
  275.     stlen = XLookupString(e,buf,128,&ks,&status);
  276.     buf[stlen] = '\0';
  277.  
  278.     if (e->window == psW) {
  279.       double dx, dy;
  280.       int movekey;
  281.  
  282.       movekey = 0;  dx = dy = 0.0;
  283.  
  284.       if      (ks==XK_Left  || ks==XK_KP_4) { dx = -0.001;  movekey = 1; }
  285.       else if (ks==XK_Right || ks==XK_KP_6) { dx =  0.001;  movekey = 1; }
  286.       else if (ks==XK_Up    || ks==XK_KP_8) { dy = -0.001;  movekey = 1; }
  287.       else if (ks==XK_Down  || ks==XK_KP_2) { dy =  0.001;  movekey = 1; }
  288.  
  289.       else if (stlen) {
  290.     if (buf[0] == '\r' || buf[0] == '\n') { /* enter */
  291.       FakeButtonPress(&psbut[PS_BOK]);
  292.     }
  293.     else if (buf[0] == '\033') {            /* ESC */
  294.       FakeButtonPress(&psbut[PS_BCANC]);
  295.     }
  296.       }
  297.  
  298.       if (movekey) {
  299.     if (e->state & ShiftMask) { dx *= 10.0;  dy *= 10.0; }
  300.     moveImage(pos_inx+dx, pos_iny+dy);
  301.       }
  302.     }
  303.     else rv = 0;
  304.   }
  305.   else rv = 0;
  306.  
  307.   if (rv==0 && (xev->type == ButtonPress || xev->type == KeyPress)) {
  308.     XBell(theDisp, 50);
  309.     rv = 1;   /* eat it */
  310.   }
  311.  
  312.   return rv;
  313. }
  314.  
  315.  
  316. /***************************************************/
  317. void PSSaveParams(fname, col)
  318. char *fname;
  319. int col;
  320. {
  321.   filename = fname;
  322.   colorType = col;
  323. }
  324.  
  325.  
  326. /***************************************************/
  327. void PSResize()
  328. {
  329.   changedScale();
  330. }
  331.  
  332.  
  333.  
  334.  
  335.  
  336.  
  337. /***************************************************/
  338. static void drawPSD(x,y,w,h)
  339. int x,y,w,h;
  340. {
  341.   char *title = "Save PostScript File...";
  342.   int  i,cx;
  343.   XRectangle xr;
  344.  
  345.   xr.x = x;  xr.y = y;  xr.width = w;  xr.height = h;
  346.   XSetClipRectangles(theDisp, theGC, 0,0, &xr, 1, Unsorted);
  347.  
  348.   XSetForeground(theDisp, theGC, infofg);
  349.   XSetBackground(theDisp, theGC, infobg);
  350.  
  351.   RBRedraw(orientRB,-1);
  352.   RBRedraw(paperRB,-1);
  353.  
  354.   for (i=0; i<PS_NBUTTS; i++) BTRedraw(&psbut[i]);
  355.  
  356.   CBRedraw(&lockCB);
  357.  
  358.   ULineString(psW, "Orientation", orientRB->x-16, orientRB->y-3-DESCENT);
  359.   ULineString(psW, "Paper Size",  paperRB->x-16,   paperRB->y-3-DESCENT);
  360.  
  361.   /* draw 'lock' arrows */
  362.   cx = 240 + 40;  /* center of xsDial */
  363.   XDrawLine(theDisp, psW, theGC, lockCB.x, lockCB.y+5,  cx+2, lockCB.y+5);
  364.   XDrawLine(theDisp, psW, theGC, cx+2, lockCB.y+5, cx+2, lockCB.y-2);
  365.  
  366.   XDrawLine(theDisp, psW, theGC, lockCB.x, lockCB.y+9,  cx-2, lockCB.y+9);
  367.   XDrawLine(theDisp, psW, theGC, cx-2, lockCB.y+9, cx-2, lockCB.y-2);
  368.  
  369.   XDrawLine(theDisp, psW, theGC, cx-2-3, lockCB.y-2+3, cx, lockCB.y-2-2);
  370.   XDrawLine(theDisp, psW, theGC, cx+2+3, lockCB.y-2+3, cx, lockCB.y-2-2);
  371.  
  372.   cx = 330 + 40;  /* center of ysDial */
  373.   XDrawLine(theDisp, psW, theGC, lockCB.x+15, lockCB.y+5,  cx-2, lockCB.y+5);
  374.   XDrawLine(theDisp, psW, theGC, cx-2, lockCB.y+5, cx-2, lockCB.y-2);
  375.  
  376.   XDrawLine(theDisp, psW, theGC, lockCB.x+15, lockCB.y+9,  cx+2, lockCB.y+9);
  377.   XDrawLine(theDisp, psW, theGC, cx+2, lockCB.y+9, cx+2, lockCB.y-2);
  378.  
  379.   XDrawLine(theDisp, psW, theGC, cx-2-3, lockCB.y-2+3, cx, lockCB.y-2-2);
  380.   XDrawLine(theDisp, psW, theGC, cx+2+3, lockCB.y-2+3, cx, lockCB.y-2-2);
  381.  
  382.   XDrawString(theDisp, psW, theGC, 10, 19, title, strlen(title));
  383.  
  384.   ULineString(psW, "Position:",   240, 190);
  385.   drawPosStr();
  386.   ULineString(psW, "Size:",       240, 190+45);
  387.   drawSizeStr();
  388.   ULineString(psW, "Resolution:", 240, 190+90);
  389.   drawResStr();
  390.  
  391.  
  392.   XSetClipMask(theDisp, theGC, None);
  393. }
  394.  
  395.  
  396. /***************************************************/
  397. static void drawPosStr()
  398. {
  399.   int x,y;
  400.   double cmx, cmy, inx, iny;
  401.   char   str[64], str1[64], *xst, *yst;
  402.  
  403.   x = 256;  y = 190 + 13;
  404.  
  405.   switch (posxType) {
  406.   case 0:  xst = "Left: ";  inx = pos_inx;                      break;
  407.   case 1:  xst = "Right:";  inx = psizex - (pos_inx + sz_inx);  break;
  408.   case 2:  xst = "X Mid:";  inx = pos_inx + sz_inx/2;           break;
  409.   }
  410.  
  411.   switch (posyType) {
  412.   case 0:  yst = "Top:  ";  iny = pos_iny;                      break;
  413.   case 1:  yst = "Bot:  ";  iny = psizey - (pos_iny + sz_iny);  break;
  414.   case 2:  yst = "Y Mid:";  iny = pos_iny + sz_iny/2;           break;
  415.   }
  416.  
  417.   cmx = inx * IN2CM;
  418.   cmy = iny * IN2CM;
  419.  
  420.   sprintf(str,  "%s %.3f\" (%.2fcm)       ", xst, inx, cmx);
  421.   sprintf(str1, "%s %.3f\" (%.2fcm)       ", yst, iny, cmy);
  422.  
  423.   XSetForeground(theDisp, theGC, infofg);
  424.   XSetBackground(theDisp, theGC, infobg);
  425.  
  426.   XSetFont(theDisp, theGC, monofont);
  427.   XDrawImageString(theDisp, psW, theGC, x, y,    str,  strlen(str));
  428.   XDrawImageString(theDisp, psW, theGC, x, y+13, str1, strlen(str1));
  429.   XSetFont(theDisp, theGC, mfont);
  430. }
  431.  
  432.   
  433. /***************************************************/
  434. static void drawSizeStr()
  435. {
  436.   int x,y;
  437.   double cmx, cmy;
  438.   char   str[64], str1[64];
  439.  
  440.   x = 256;  y = 190+13+45;
  441.  
  442.   cmx = sz_inx * IN2CM;
  443.   cmy = sz_iny * IN2CM;
  444.  
  445.   sprintf(str,  "%.3f\" x %.3f\"        ", sz_inx, sz_iny);
  446.   sprintf(str1, "%.2fcm x %.2fcm        ", cmx, cmy);
  447.  
  448.   XSetForeground(theDisp, theGC, infofg);
  449.   XSetBackground(theDisp, theGC, infobg);
  450.   XSetFont(theDisp, theGC, monofont);
  451.  
  452.   XDrawImageString(theDisp, psW, theGC, x, y,    str, strlen(str));
  453.   XDrawImageString(theDisp, psW, theGC, x, y+13, str1, strlen(str1));
  454.   XSetFont(theDisp, theGC, mfont);
  455. }
  456.  
  457.   
  458. /***************************************************/
  459. static void drawResStr()
  460. {
  461.   int x,y;
  462.   char   str[64];
  463.  
  464.   x = 256;  y = 190 + 13 + 90;
  465.  
  466.   sprintf(str,  "%ddpi x %ddpi        ", dpix, dpiy);
  467.  
  468.   XSetForeground(theDisp, theGC, infofg);
  469.   XSetBackground(theDisp, theGC, infobg);
  470.   XSetFont(theDisp, theGC, monofont);
  471.   XDrawImageString(theDisp, psW, theGC, x, y, str, strlen(str));
  472.   XSetFont(theDisp, theGC, mfont);
  473. }
  474.  
  475.   
  476.   
  477.   
  478. /***************************************************/
  479. static void drawPage()
  480. {
  481.   int  i;
  482.  
  483.   /* draw page */
  484.   XSetForeground(theDisp, theGC, infobg);
  485.   XFillRectangle(theDisp, pageF, theGC, pageRect.x+1, pageRect.y+1,
  486.          pageRect.width-1, pageRect.height-1);
  487.  
  488.   XSetForeground(theDisp, theGC, infofg);
  489.   XDrawRectangle(theDisp, pageF, theGC, pageRect.x, pageRect.y,
  490.          pageRect.width, pageRect.height);
  491.  
  492.   drawIRect(1);
  493. }
  494.  
  495.  
  496. /***************************************************/
  497. static void clickPSD(x,y)
  498. int x,y;
  499. {
  500.   int i,j;
  501.   BUTT *bp;
  502.  
  503.   /* check BUTTs */
  504.  
  505.   for (i=0; i<PS_NBUTTS; i++) {
  506.     bp = &psbut[i];
  507.     if (PTINRECT(x, y, bp->x, bp->y, bp->w, bp->h)) break;
  508.   }
  509.  
  510.   if (i<PS_NBUTTS) {  /* found one */
  511.     if (BTTrack(bp)) doCmd(i);
  512.   }
  513.  
  514.   /* check RBUTTs */
  515.  
  516.   else if ((i=RBClick(orientRB,x,y)) >= 0) {
  517.     if (RBTrack(orientRB, i)) changedPaper();
  518.   }
  519.  
  520.   else if ((i=RBClick(paperRB,x,y)) >= 0) {
  521.     if (RBTrack(paperRB, i)) changedPaper();
  522.   }
  523.  
  524.   /* check CBUTTs */
  525.  
  526.   else if (CBClick(&lockCB,x,y)) {
  527.     if (CBTrack(&lockCB) && lockCB.val) {  /* turned on lock */
  528.       DSetVal(&ysDial, xsDial.val);        /* copy xsDial.val to ysDial */
  529.       changedScale();
  530.     }
  531.   }
  532. }
  533.  
  534.  
  535.  
  536. /***************************************************/
  537. static void clickPage(mx,my)
  538. int mx,my;
  539. {
  540.   Window       rW,cW;
  541.   int          rx,ry,x,y;
  542.   unsigned int mask;
  543.   double       offx, offy, newx, newy;
  544.  
  545.   /* compute offset (in inches) between 'drag point' and 
  546.      the top-left corner of the image */
  547.  
  548.   offx = ((mx - pageRect.x) / in2pix) - pos_inx;
  549.   offy = ((my - pageRect.y) / in2pix) - pos_iny;
  550.  
  551.   /* if clicked outside of image rectangle, ignore */
  552.   if (offx<0.0 || offy < 0.0 || offx>=sz_inx || offy >= sz_iny) return;
  553.  
  554.   while (1) {
  555.     if (XQueryPointer(theDisp,pageF,&rW,&cW,&rx,&ry,&x,&y,&mask)) {
  556.       if (!(mask & Button1Mask)) break;    /* button released */
  557.  
  558.       /* compute new pos_inx, pos_iny based on x,y coords */
  559.       newx = ((x-pageRect.x) / in2pix) - offx;
  560.       newy = ((y-pageRect.y) / in2pix) - offy;
  561.  
  562.       moveImage(newx, newy);
  563.     }
  564.   }
  565. }
  566.  
  567.  
  568.  
  569. /***************************************************/
  570. static void doCmd(cmd)
  571. int cmd;
  572. {
  573.   switch (cmd) {
  574.   case PS_BOK:    writePS();    PSDialog(0);  break;
  575.  
  576.   case PS_BCANC:  PSDialog(0);  break;
  577.  
  578.   case PS_BCENT:  drawIRect(0);
  579.                   centerImage();
  580.                   drawIRect(1);
  581.                   drawPosStr();
  582.                   break;
  583.  
  584.   case PS_BMAX:   drawIRect(0);
  585.                   maxImage();
  586.                   drawIRect(1);
  587.                   drawPosStr();
  588.                   drawSizeStr();
  589.                   drawResStr();
  590.                   break;
  591.  
  592.   case PS_BPOSX:  posxType = (posxType + 1) % 3;
  593.                   drawPosStr();
  594.                   break;
  595.  
  596.   case PS_BPOSY:  posyType = (posyType + 1) % 3;
  597.                   drawPosStr();
  598.                   break;
  599.  
  600.   default:        break;
  601.   }
  602. }
  603.  
  604.  
  605. /***************************************************/
  606. static void changedScale()
  607. {
  608.   double oldx,oldy;
  609.  
  610.   drawIRect(0);
  611.  
  612.   if (lockCB.val) {
  613.     if      (tracking == 1) DSetVal(&ysDial, xsDial.val);
  614.     else if (tracking == 2) DSetVal(&xsDial, ysDial.val);
  615.   }
  616.  
  617.   oldx = pos_inx;  oldy = pos_iny;
  618.   setScale();
  619.  
  620.   drawIRect(1);
  621.  
  622.   if (pos_inx != oldx || pos_iny != oldy ||
  623.       posxType != 0 || posyType != 0) drawPosStr();
  624.   drawSizeStr();
  625.   drawResStr();
  626.   XFlush(theDisp);
  627. }
  628.  
  629.  
  630. /***************************************************/
  631. static void setScale()
  632. {
  633.   double hsx, hsy;
  634.  
  635.   sz_inx = (double) eWIDE / PIX2INCH * (xsDial.val / 100.0);  
  636.   sz_iny = (double) eHIGH / PIX2INCH * (ysDial.val / 100.0);  
  637.  
  638.   /* round to integer .001ths of an inch */
  639.   sz_inx = floor(sz_inx * 1000.0 + 0.5) / 1000.0;
  640.   sz_iny = floor(sz_iny * 1000.0 + 0.5) / 1000.0;
  641.  
  642.   dpix = (int) (PIX2INCH / (xsDial.val / 100.0));  
  643.   dpiy = (int) (PIX2INCH / (ysDial.val / 100.0));  
  644.  
  645.   /* make sure 'center' of image is still on page */
  646.   hsx = sz_inx/2;  hsy = sz_iny/2;
  647.   RANGE(pos_inx, -hsx, psizex-hsx);
  648.   RANGE(pos_iny, -hsy, psizey-hsy);
  649.  
  650.   /* round to integer .001ths of an inch */
  651.   pos_inx = floor(pos_inx * 1000.0 + 0.5) / 1000.0;
  652.   pos_iny = floor(pos_iny * 1000.0 + 0.5) / 1000.0;
  653.  
  654. }
  655.  
  656.  
  657. /***************************************************/
  658. static void changedPaper()
  659. {
  660.   setPaper();
  661.   XClearWindow(theDisp, pageF);
  662.   centerImage();
  663.   drawPosStr();
  664.   drawPage();
  665. }
  666.  
  667.  
  668. /***************************************************/
  669. static void setPaper()
  670. {
  671.   double tmp;
  672.  
  673.   psizex = paperSize[RBWhich(paperRB)][0];
  674.   psizey = paperSize[RBWhich(paperRB)][1];
  675.  
  676.   in2pix = (double) PMAX / psizey;
  677.  
  678.   if (RBWhich(orientRB)==ORNT_LAND) {
  679.     tmp = psizex;  psizex = psizey;  psizey = tmp;
  680.   }
  681.  
  682.   pageRect.x = (int) ((PMAX/2) - ((psizex/2.0) * in2pix));
  683.   pageRect.y = (int) ((PMAX/2) - ((psizey/2.0) * in2pix));
  684.   pageRect.width  = (int) (psizex * in2pix);
  685.   pageRect.height = (int) (psizey * in2pix);
  686. }
  687.  
  688.  
  689. /***************************************************/
  690. static void drawIRect(draw)
  691. int draw;
  692. {
  693.   int x,y,w,h;
  694.   XRectangle xr;
  695.  
  696.   x = pageRect.x + (int) (pos_inx * in2pix);
  697.   y = pageRect.y + (int) (pos_iny * in2pix);
  698.   w = sz_inx * in2pix;
  699.   h = sz_iny * in2pix;
  700.  
  701.   xr.x = pageRect.x + 1;
  702.   xr.y = pageRect.y + 1;
  703.   xr.width  = pageRect.width - 1;
  704.   xr.height = pageRect.height - 1;
  705.  
  706.   if (draw) XSetForeground(theDisp, theGC, infofg);
  707.        else XSetForeground(theDisp, theGC, infobg);
  708.  
  709.   XSetClipRectangles(theDisp, theGC, 0,0, &xr, 1, Unsorted);
  710.   XDrawRectangle(theDisp, pageF, theGC, x, y, w, h);
  711.   XDrawLine(theDisp, pageF, theGC, x, y, x+w, y+h);
  712.   XDrawLine(theDisp, pageF, theGC, x, y+h, x+w, y);
  713.   XSetClipMask(theDisp, theGC, None);
  714. }
  715.  
  716.  
  717.  
  718. /***************************************************/
  719. static void centerImage()
  720. {
  721.   pos_inx = psizex/2 - sz_inx/2;
  722.   pos_iny = psizey/2 - sz_iny/2;
  723.  
  724.   /* round to integer .001ths of an inch */
  725.   pos_inx = floor(pos_inx * 1000.0 + 0.5) / 1000.0;
  726.   pos_iny = floor(pos_iny * 1000.0 + 0.5) / 1000.0;
  727. }
  728.  
  729.  
  730. /***************************************************/
  731. static void maxImage()
  732. {
  733.   double scx, scy;
  734.  
  735.   sz_inx = psizex - 1.0;    /* half inch margin on all sides */
  736.   sz_iny = psizey - 1.0;
  737.  
  738.   /* choose the smaller scaling factor */
  739.   scx = sz_inx / eWIDE;
  740.   scy = sz_iny / eHIGH;
  741.  
  742.   if (scx < scy) { sz_iny = eHIGH * scx; }
  743.             else { sz_inx = eWIDE * scy; }
  744.  
  745.   DSetVal(&xsDial, (int) ((100 * (sz_inx * PIX2INCH) / eWIDE) + .5));
  746.   DSetVal(&ysDial, xsDial.val);
  747.  
  748.   sz_inx = (double) eWIDE / PIX2INCH * (xsDial.val / 100.0);  
  749.   sz_iny = (double) eHIGH / PIX2INCH * (ysDial.val / 100.0);  
  750.  
  751.   /* round to integer .001ths of an inch */
  752.   sz_inx = floor(sz_inx * 1000.0 + 0.5) / 1000.0;
  753.   sz_iny = floor(sz_iny * 1000.0 + 0.5) / 1000.0;
  754.  
  755.   dpix = (int) (PIX2INCH / (xsDial.val / 100.0));  
  756.   dpiy = (int) (PIX2INCH / (ysDial.val / 100.0));  
  757.  
  758.   pos_inx = psizex/2 - sz_inx/2;
  759.   pos_iny = psizey/2 - sz_iny/2;
  760.  
  761.   /* round to integer .001ths of an inch */
  762.   pos_inx = floor(pos_inx * 1000.0 + 0.5) / 1000.0;
  763.   pos_iny = floor(pos_iny * 1000.0 + 0.5) / 1000.0;
  764. }
  765.  
  766.  
  767. /***************************************************/
  768. static void moveImage(newx,newy)
  769. double newx, newy;
  770. {
  771.   double hsx, hsy;
  772.  
  773.   hsx = sz_inx/2;  hsy = sz_iny/2;
  774.  
  775.   /* round to integer .001ths of an inch */
  776.   newx = floor(newx * 1000.0 + 0.5) / 1000.0;
  777.   newy = floor(newy * 1000.0 + 0.5) / 1000.0;
  778.  
  779.   /* keep center of image within page limits */
  780.   RANGE(newx, -hsx, psizex-hsx);
  781.   RANGE(newy, -hsy, psizey-hsy);
  782.  
  783.   if (newx != pos_inx || newy != pos_iny) {  /* moved */
  784.     drawIRect(0);
  785.     pos_inx = newx;
  786.     pos_iny = newy;
  787.     drawIRect(1);
  788.     drawPosStr();
  789.   }
  790. }
  791.  
  792.  
  793. /***************************************************/
  794. static void writePS()
  795. {
  796.   FILE *fp;
  797.   int   i, j, q, err, rpix, gpix, bpix, nc;
  798.   int   iw, ih, ox, oy, slen, lwidth, bits, colorps;
  799.   byte *inpix, *bwpic, *rmap, *gmap, *bmap;
  800.   
  801.   inpix = epic;  bwpic = NULL;  rmap = r;  gmap = g;  bmap = b;
  802.   nc = numcols;
  803.  
  804.   fp = OpenOutFile(filename);
  805.   if (!fp) return;
  806.  
  807.   WaitCursor();
  808.   
  809.  
  810.   bwpic = HandleBWandReduced(colorType, &nc, &rmap, &gmap, &bmap);
  811.   if (bwpic) inpix = bwpic;
  812.  
  813.   /* monocity check.  if the image is mono, save it that way to save space */
  814.  
  815.   if (colorType == F_FULLCOLOR || colorType == F_REDUCED) {
  816.     for (i=0; i<nc && rmap[i]==gmap[i] && rmap[i]==bmap[i]; i++);
  817.     if (i==nc) colorType = F_GREYSCALE;    /* made it all the way through */
  818.   }
  819.     
  820.  
  821.   /* printed image will have size iw,ih (in picas) */
  822.   iw = (int) (sz_inx * 72.0 + 0.5);
  823.   ih = (int) (sz_iny * 72.0 + 0.5);   
  824.  
  825.   /* compute offset to bottom-left of image (in picas) */
  826.   ox = (int) (pos_inx * 72.0 + 0.5);
  827.   oy = (int) ((psizey - (pos_iny + sz_iny)) * 72.0 + 0.5);
  828.  
  829.  
  830.   /*** write PostScript header ***/
  831.  
  832.  
  833.   fprintf(fp,"%%!PS-Adobe-2.0 EPSF-2.0\n");
  834.   fprintf(fp,"%%%%Title: %s\n",filename);
  835.   fprintf(fp,"%%%%Creator: XV %s  -  by John Bradley\n",REVDATE);
  836.  
  837.   if (RBWhich(orientRB)==ORNT_LAND)    /* Landscape mode */
  838.     fprintf(fp,"%%%%BoundingBox: %d %d %d %d\n", 
  839.         (int) (pos_iny * 72.0 + 0.5),
  840.         (int) (pos_inx * 72.0 + 0.5),
  841.         (int) (pos_iny * 72.0 + 0.5) + iw,
  842.         (int) (pos_inx * 72.0 + 0.5) + ih);
  843.   else 
  844.     fprintf(fp,"%%%%BoundingBox: %d %d %d %d\n", ox, oy, ox+iw, oy+ih);
  845.  
  846.   fprintf(fp,"%%%%Pages: 1\n");
  847.   fprintf(fp,"%%%%DocumentFonts:\n");
  848.   fprintf(fp,"%%%%EndComments\n");
  849.   
  850.  
  851.   switch (colorType) {
  852.   case F_FULLCOLOR:
  853.   case F_REDUCED:   slen = eWIDE*3;      bits = 8;  colorps = 1;  break;
  854.   case F_GREYSCALE: slen = eWIDE;        bits = 8;  colorps = 0;  break;
  855.   case F_BWDITHER:  slen = (eWIDE+7)/8;  bits = 1;  colorps = 0;  break;
  856.   default:  /* never happen */
  857.     slen = eWIDE*3;      bits = 8;  colorps = 1;  break;
  858.   }
  859.   
  860.   epsPreview(fp, inpix, colorType);
  861.  
  862.   fprintf(fp,"%%%%EndProlog\n\n");
  863.  
  864.   fprintf(fp,"%% remember original state\n");
  865.   fprintf(fp,"/origstate save def\n\n");
  866.  
  867.   fprintf(fp,"%% build a temporary dictionary\n");
  868.   fprintf(fp,"10 dict begin\n\n");
  869.  
  870.   fprintf(fp,"%%%%Page: 1 1\n");
  871.  
  872.   fprintf(fp,"%% define string to hold a scanline's worth of data\n");
  873.   fprintf(fp,"/pix %d string def\n\n", slen);
  874.  
  875.   if (RBWhich(orientRB)==ORNT_LAND) {   /* Landscape mode */
  876.     fprintf(fp,"%% print in landscape mode\n");
  877.     fprintf(fp,"90 rotate 0 %d translate\n\n",(int) (-psizey*72.0));
  878.   }
  879.     
  880.   fprintf(fp,"%% lower left corner\n");
  881.   fprintf(fp,"%d %d translate\n\n",ox,oy);
  882.  
  883.   fprintf(fp,"%% size of image (on paper, in 1/72inch coords)\n");
  884.   fprintf(fp,"%d %d scale\n\n",iw,ih);
  885.  
  886.   if (colorType == F_FULLCOLOR || colorType == F_REDUCED) 
  887.     psColorImage(fp);
  888.  
  889.   fprintf(fp,"%% dimensions of data\n");
  890.   fprintf(fp,"%d %d %d\n\n",eWIDE,eHIGH,bits);
  891.  
  892.   fprintf(fp,"%% mapping matrix\n");
  893.   fprintf(fp,"[%d 0 0 %d 0 %d]\n\n", eWIDE, -eHIGH, eHIGH);
  894.  
  895.   fprintf(fp,"{currentfile pix readhexstring pop}\n");
  896.  
  897.   if (colorps) fprintf(fp,"false 3 colorimage\n");
  898.           else fprintf(fp,"image\n");
  899.  
  900.  
  901.   /* write the actual image data */
  902.  
  903.  
  904.   if (colorType == F_BWDITHER) {   /* 1-bit BWDither code */
  905.     err = writeBWStip(fp, inpix, "");
  906.   }
  907.  
  908.   else {  /* FULLCOLOR, REDUCED, and GREYSCALE handling code */
  909.     err = 0;
  910.  
  911.     for (i=0; i<eHIGH && err != EOF; i++) {
  912.       lwidth = 0;
  913.       putc('\n',fp);
  914.  
  915.       if ((i&0x1f) == 0) WaitCursor();
  916.  
  917.       for (j=0; j<eWIDE && err != EOF; j++) {
  918.     rpix = rmap[*inpix];
  919.     gpix = gmap[*inpix];
  920.     bpix = bmap[*inpix];
  921.     
  922.     if (colorps) { 
  923.       err = fprintf(fp,"%02x%02x%02x",rpix,gpix,bpix);
  924.       lwidth+=6;
  925.     }
  926.       
  927.     else {  /* greyscale */
  928.       q = (rpix*21 + gpix*32 + bpix*11) / 64;
  929.       err = fprintf(fp,"%02x", q);
  930.       lwidth+=2;
  931.     }
  932.  
  933.     if (lwidth>70) { putc('\n',fp); lwidth = 0; }
  934.     inpix++;
  935.       }
  936.     }
  937.   }
  938.  
  939.   fprintf(fp,"\n\nshowpage\n\n");
  940.  
  941.   fprintf(fp,"%% stop using temporary dictionary\n");
  942.   fprintf(fp,"end\n\n");
  943.  
  944.   fprintf(fp,"%% restore original state\n");
  945.   fprintf(fp,"origstate restore\n\n");
  946.   fprintf(fp,"%%%%Trailer\n");
  947.  
  948.   if (bwpic) free(bwpic);
  949.  
  950.   if (CloseOutFile(fp, filename, (err==EOF)) == 0) {
  951.     DirBox(0);
  952.     LoadCurrentDirectory();   /* wrote file: rescan directory */
  953.   }
  954.  
  955.   SetCursors(-1);
  956. }
  957.  
  958.  
  959. /**********************************************/
  960. static void psColorImage(fp)
  961. FILE *fp;
  962. {
  963.   /* spits out code that checks if the PostScript device in question
  964.      knows about the 'colorimage' operator.  If it doesn't, it defines
  965.      'colorimage' in terms of image (ie, generates a greyscale image from
  966.      RGB data) */
  967.  
  968.  
  969.   fprintf(fp,"%% see if we have the 'colorimage' operator.\n");
  970.   fprintf(fp,"%% define one if we don't\n");
  971.   fprintf(fp,"/colorimage where   %% do we know about 'colorimage'?\n");
  972.   fprintf(fp,"  { pop }           %% yes: pop off the 'dict' returned\n");
  973.   fprintf(fp,"  {                 %% no:  define one\n");
  974.   fprintf(fp,"    /str1 1 string def\n");
  975.   fprintf(fp,"    /str3 3 string def\n");
  976.   fprintf(fp,"    /colorimage\n");
  977.   fprintf(fp,"      { pop pop     %% pop off 'false', '3' operands\n");
  978.   fprintf(fp,"        pop         %% pop off old 'readhexstring' proc\n");
  979.   fprintf(fp,"                    %% and define a new one for 'image'\n");
  980.   fprintf(fp,"        { currentfile str3 readhexstring pop pop\n");
  981.   fprintf(fp,"          str1 0    %% for the 'put' below\n");
  982.   fprintf(fp,"          str3 0 get 20 mul    %% Red\n");
  983.   fprintf(fp,"          str3 1 get 32 mul    %% Green\n");
  984.   fprintf(fp,"          str3 2 get 12 mul    %% Blue\n");
  985.   fprintf(fp,"          add add 64 idiv      %% I = .5G + .31R + .18B\n");
  986.   fprintf(fp,"          put str1  %% str1 = intensity of R,G,B triplet\n");
  987.   fprintf(fp,"        } image\n");
  988.   fprintf(fp,"      } def         %% end of colorimage def\n");
  989.   fprintf(fp,"  } ifelse          %% end of 'false' case\n");
  990.   fprintf(fp,"\n");
  991. }
  992.  
  993.  
  994. /**********************************************/
  995. static void epsPreview(fp, pic, colorType)
  996.      FILE *fp;
  997.      byte *pic;
  998.      int   colorType;
  999. {
  1000.   byte *prev;
  1001.  
  1002.   /* put in an EPSI preview */
  1003.   
  1004.   if (colorType != F_BWDITHER) { /* have to generate a preview */
  1005.     prev = (byte *) malloc(eWIDE * eHIGH);
  1006.     if (!prev) {
  1007.       fprintf(stderr,"Unable to malloc in epsPreview\n");
  1008.       return;
  1009.     }
  1010.     FSDither(epic, eWIDE, eHIGH, prev);
  1011.   }
  1012.   else prev = pic;
  1013.   
  1014.   fprintf(fp,"%%%%BeginPreview: %d %d %d %d\n", eWIDE, eHIGH, 1, 
  1015.       (eWIDE/(72*4) + 1) * eHIGH);
  1016.  
  1017.   writeBWStip(fp, prev, "% ");
  1018.  
  1019.   fprintf(fp,"%%%%EndPreview\n");
  1020.  
  1021.   if (colorType == F_BWDITHER) free(prev);
  1022. }
  1023.  
  1024.  
  1025. /***********************************/
  1026. static int writeBWStip(fp, pic, prompt)
  1027.      FILE *fp;
  1028.      byte *pic;
  1029.      char *prompt;
  1030. {
  1031.   /* write the given 'pic' (B/W stippled, 1 byte per pixel, 0=blk,1=wht) 
  1032.      out as hexadecimal, max of 72 hex chars per line.
  1033.  
  1034.      returns '0' if everythings fine, 'EOF' if writing failed */
  1035.  
  1036.   int err, i, j, lwidth;
  1037.   byte outbyte, bitnum, bit;
  1038.  
  1039.   err = 0;
  1040.  
  1041.   for (i=0; i<eHIGH && err != EOF; i++) {
  1042.     fprintf(fp, "%s", prompt);
  1043.  
  1044.     outbyte = bitnum = lwidth = 0;
  1045.  
  1046.     if ((i&0x3f) == 0) WaitCursor();
  1047.  
  1048.     for (j=0; j<eWIDE && err != EOF; j++) {
  1049.       bit = *pic;
  1050.       outbyte = (outbyte<<1) | ((~bit)&0x01);
  1051.       bitnum++;
  1052.  
  1053.       if (bitnum==8) {
  1054.     err = fprintf(fp,"%02x",outbyte);
  1055.     lwidth+=2;
  1056.     outbyte = bitnum = 0;
  1057.       }
  1058.  
  1059.       if (lwidth>=72 && j+1<eWIDE) { fprintf(fp, "\n%s", prompt); lwidth = 0; }
  1060.       pic++;
  1061.     }
  1062.  
  1063.     if (bitnum) {   /* few bits left over... */
  1064.       for ( ; bitnum<8; bitnum++) outbyte <<= 0;
  1065.       err = fprintf(fp,"%02x",outbyte);
  1066.       lwidth+=2;
  1067.     }
  1068.  
  1069.     fprintf(fp, "\n");
  1070.   }
  1071.  
  1072.   return err;
  1073. }
  1074.  
  1075.  
  1076.  
  1077.